package com.gokzzz.killdemo.util;


import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.TimeUnit;

/**
 * @author gokzzz
 * @date 2022-09-10 10:50
 */
@Component
@Slf4j
@SuppressWarnings({"unchecked", "all"})
public class RedisUtil {

    @Resource
    private RedisTemplate<String, Object> redisTemplate;

    /**
     * lua脚本，保证操作的原子性。
     * if redis.call('get', KEYS[1]) == ARGV[1]
     *     then
     *         return redis.call('del', KEYS[1])
     *     else
     *         return 0
     * end
     */
    public static final String DEL_SETNX_SCRIPT = "if redis.call('get', KEYS[1]) == ARGV[1]\n" +
            "    then\n" +
            "        return redis.call('del', KEYS[1])\n" +
            "    else\n" +
            "        return 0\n" +
            "end";

    /**
     * redis实现分布式锁
     *
     * @param key
     * @param value
     * @param time  秒单位
     * @return
     */
    public Boolean setnx(String key, String value, int time) {
        return redisTemplate.opsForValue().setIfAbsent(key, value, time, TimeUnit.SECONDS);
    }


    /**
     * 手动失效redis分布式锁
     *
     * @param key
     * @param value
     */
    public Long delnx(String key, String value) {
        DefaultRedisScript<Long> script = new DefaultRedisScript<>(DEL_SETNX_SCRIPT, Long.class);
        return redisTemplate.execute(script, Collections.singletonList(key), value);
    }

    //============================String=============================

    /**
     * 普通缓存获取
     *
     * @param key 键
     * @return 值
     */
    public Object get(String key) {
        return key == null ? null : redisTemplate.opsForValue().get(key);
    }

    /**
     * 普通缓存放入
     *
     * @param key   键
     * @param value 值
     * @return true成功 false失败
     */
    public boolean set(String key, Object value) {
        try {
            redisTemplate.opsForValue().set(key, value);
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }

    }


}
